<?php

  /**
   * Post
   *
   * ORM для таблицы постов
   *
   * @property      string       $date         дата публикации
   * @property      string       $title        заголовок
   * @property      string       $content      содержимое
   * @property      string       $search_text  текст для поискового запроса
   * @property      string       $type         тип поста ('blog','news','public')
   * @property      string       $last_comment последний комментарий
   * @property      int          $lc_stamp     время создания последнего комментария
   * @property      int          $is_temporary временный пост
   * @property-read Evaluation[] $evaluation   оценки публикаций
   * @property-read Tag[]        $tags         теги
   * @property-read Photo[]      $photos       прикрепленные фотографии
   * @property-read int          $balls        суммарное кол-во баллов
   * @property-read float        $averageBall  средний балл
   * @method Post announcement() выборка для анонса
   * @method Post resonance()    выборка топовых постов
   * @method Post blog()         выборка блогов
   * @method Post news()         выборка новостей
   * @method Post public()       выборка публикаций
   */

  final class Post extends CommentRecord
  {
  // типы постов
    const BLOGS     = "blog";
    const NEWS      = "news";
    const PUBLICS   = "public";
    const RESONANCE = "resonance";

  // имя папки с фотографиями
    const PHOTOS = "illustrations";

    /**
     * текст
     *
     * @var string
     */
    private $_content = "";

    /**
     * вернуть экземпляр модели
     *
     * @return Post
     * @access public
     */
    public static function model($className = __CLASS__)
    {
      return parent::model($className);
    }

    /**
     * правила проверки атрибутов модели
     *
     * @return array[]
     * @access public
     */
    public function rules()
    {
      return array(
        array("id", "exist", "className" => "Post", "allowEmpty" => false, "on" => "update"),
        array("date", "match", "pattern" => "/^\d{4}\-\d{2}\-\d{2}$/"),
        array("title,content", "required"),
        array("title", "length", "max" => $this->fieldSize("title"), "encoding" => "utf-8", "skipOnError" => true),
        array("search_text,last_comment,lc_stamp,is_temporary", "safe"),
        array("type", "in", "range" => $this->enum("type"), "allowEmpty" => false)
      ) + parent::rules();
    }

    /**
     * действия перед проверкой
     *
     * @return bool
     * @access protected
     */
    protected function beforeValidate()
    {
      if ($success = parent::beforeValidate())
      {
        $this->title   = strip_tags($this->title);
        $this->content = self::validHTML($this->_content = $this->content, false);
      }

      return $success;
    }

    /**
     * действия после проверки
     *
     * @return void
     * @access protected
     */
    protected function afterValidate()
    {
      parent::afterValidate();

      $this->content = $this->_content;
    }

    /**
     * параметры выборки
     *
     * @return array[]
     * @access public
     */
    public function defaultScope()
    {
      return array(
        "condition" => "`is_temporary` is null or `is_temporary`='0'",
        "order"     => "`date` desc,`title`"
      ) +  parent::defaultScope();
    }

    /**
     * наборы фильтров для выборки
     *
     * @return array[]
     * @access public
     */
    public function scopes()
    {
      return array(
        "announcement" => array("limit" => $this->app->postLimit),
        "resonance"    => array(
          "select" => "`t`.*",
          "join"   => "inner join `comments` on `table`='posts' and `rec_id`=`t`.`id`",
          "group"  => "`rec_id`",
          "order"  => "count(`rec_id`) desc,`date` desc,`title`"
        )
      ) + $this->enumScopes("type") + parent::scopes();
    }

    /**
     * связи с другими таблицами
     *
     * @return array[]
     * @access public
     */
    public function relations()
    {
      return array(
        "evaluation" => array(self::HAS_MANY, "Evaluation", "post_id"),
        "tags"       => array(self::HAS_MANY, "Tag", "rec_id"),
        "photos"     => array(self::HAS_MANY, "Photo", "post_id")
      ) + parent::relations();
    }

    /**
     * действия перед сохранением
     *
     * @return bool
     * @access protected
     */
    protected function beforeSave()
    {
      if ($success = parent::beforeSave())
      {
        if ($this->date === null)
          $this->date = date("Y-m-d");

        $this->content     = self::validHTML($this->content);
        $this->search_text = self::stripDesc($this->content);
      }

      return $success;
    }

    /**
     * действия перед удалением
     *
     * @return bool
     * @access protected
     */
    protected function beforeDelete()
    {
      if ($success = parent::beforeDelete())
      {
        $id = $this->id;
        Evaluation::model()->deleteAllByAttributes(array("post_id" => $id));
        Tag::model()->deleteAllByAttributes(array("rec_id" => $id));

        foreach ($this->photos as $photo)
          $photo->delete();
      }

      return $success;
    }

    /**
     * вернуть суммарное кол-во баллов для поста
     *
     * @return int
     * @access public
     */
    public function getBalls()
    {
      return self::$db->createCommand("select sum(`balls`) from `evaluation` where `post_id`='$this->id'")->queryScalar();
    }

    /**
     * вернуть средний балл для поста
     *
     * @return float
     * @access public
     */
    public function getAverageBall()
    {
      return $this->balls / count($this->evaluation);
    }

    /**
     * вернуть URL главного изображения
     *
     * @param string $type тип изображения
     * @return string
     * @access public
     */
    public function getMainPhoto($type = ContentController::IMG_FULL)
    {
      $mainImg = null;
      foreach ($this->photos as $photo)
        if ($photo->is_main)
        {
          $mainImg = $photo;
          break;
        }
      return $mainImg ? join("/", array($this->app->contentUrl, $type, self::PHOTOS, $mainImg->photo)) : "";
    }

    /**
     * вернуть кол-во постов у пользователя
     *
     * @param int $uid идентификатор пользователя
     * @return int
     * @access public
     */
    public function postCount($uid)
    {
      return $this->count("`user_id`='$uid'");
    }

    /**
     * вернуть идентификаторы временных постов пользователя
     *
     * @param int $uid идентификатор пользователя
     * @return int[]
     * @access public
     */
    public static function getTemporary($uid)
    {
      return self::$db->createCommand(
        "select `id` from `posts` where not(`is_temporary` is null or `is_temporary`='0') and `user_id`='$uid'"
      )->queryColumn();
    }

    /**
     * вернуть текст, очищенный от тегов
     *
     * @return string
     * @access public
     */
    public static function stripDesc($text)
    {
      // замена на одинарные пробелы
      return trim(preg_replace(array(
        "/&\w+;/u",           // html-сущности
        "/[^\w\x7F-\xFF\s]/", // символы
        "/\s+/u"              // множественные пробелы
      ), " ", strip_tags($text)));
    }
  }

?>
